﻿using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using System.Threading.Tasks;
using System.Windows.Forms;
using SocksToggle.Properties;
using System.Net;
using System.IO;

namespace SocksToggle
{
    //
    class ProcessIcon : IDisposable
    {
        // essential members
        // icon
        NotifyIcon notifyIcon;
        // service status
        bool serviceOn;
        // init with an icon
        public ProcessIcon()
        {
            notifyIcon = new NotifyIcon();
        }

        // just two icons for now
        System.Drawing.Icon getIcon(bool serviceStatus)
        {
            switch (serviceStatus)
            {
                case true:
                    return Resources.network;
                default:
                    return Resources.network_close;
            }
        }

        // Display : call in Main
        public void Display()
        {
            notifyIcon.Text = Properties.Settings.Default.TextDefault;
            // check status and use icon accordingly
            getServiceStatus();
            notifyIcon.Icon = getIcon(serviceOn);

            // make icon visable
            notifyIcon.Visible = true;
            
            // attach click event
            notifyIcon.MouseClick += new MouseEventHandler(iconClick);

            // attach a context menu
            notifyIcon.ContextMenuStrip = new ContextMenu().Create();
        }

        // implement IDisposable.Dispose
        public void Dispose()
        {
            notifyIcon.Dispose();
        }

        // event for click
        void iconClick(object sender, MouseEventArgs e)
        {
            switch (e.Button)
            {
                // toggle service when left click
                case MouseButtons.Left:
                    toggleService();
                    break;
                default:
                    return;
            }
        }

        // call back which exams response and then return int accordingly
        delegate int CallBack(HttpWebResponse response);

        // api helper, per tenx api docs
        int apiHelper(string apiString, string method, string data, CallBack callback)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Properties.Settings.Default.BaseToggleUrl + apiString);
            request.Headers.Add(Properties.Settings.Default.UserNameHeader);
            request.Headers.Add(Properties.Settings.Default.AuthorizationHeader);
            request.Method = method;
            //send data, be ware of autoescaping with settings. Thus data should be provided as normal 
            if (data.Length > 0)
            {
                //Define a cache policy for this request only.
                request.CachePolicy = new System.Net.Cache.HttpRequestCachePolicy(System.Net.Cache.HttpRequestCacheLevel.BypassCache);
                // Set the content type of the data being put.
                request.ContentType = "application/json;charset=utf-8";
                // Write data:q
                using (var streamWriter = new StreamWriter(request.GetRequestStream()))
                {
                    streamWriter.Write(data);
                    streamWriter.Flush();
                }
            }
            notifyIcon.Text = "Waiting for response...";
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            notifyIcon.Text = "Checking response...";
            int returnCode = callback(response);
            notifyIcon.Text = Properties.Settings.Default.TextDefault;
            return returnCode;
        }

        // check status, per tenx api docs
        void getServiceStatus()
        {
            try
            {
                int gotStatus = apiHelper("", Properties.Settings.Default.StatucCheckMethod, "", getServiceStatus);
                if (gotStatus != 1)
                    serviceOn = false;
            }
            catch (Exception exception)
            {
                //change icon text to error
                notifyIcon.Text = String.Format("Can't check status:{0}", exception.Message);
            }
        }

        // deal with response from checking status
        int getServiceStatus(HttpWebResponse response)
        {
            switch (response.StatusCode)
            {
                case HttpStatusCode.OK:
                    Stream receiveStream = response.GetResponseStream();
                    string response_text = new StreamReader(receiveStream).ReadToEnd();
                    // check whether service is running
                    if (response_text.Contains(Properties.Settings.Default.StatusCheckOnString))
                    {
                        serviceOn = true;
                    }
                    else
                        serviceOn = false;
                    notifyIcon.Text = String.Format("Sevice is {0}.", serviceOn ? "on" : "off");
                    return 1;
                default:
                    notifyIcon.Text = "Can't check status: Unknown Respond";
                    return 0;
            }
        }

        // command worked if response is OK. per tenx api docs
        int toggleService(HttpWebResponse response)
        {
            if (response.StatusCode == HttpStatusCode.OK)
                return 1;
            else
                return 0;
        }

        // toggle service
        void toggleService()
        {
            int status;
            //try catch all exceptions
            try
            {
                // toggle service
                switch (serviceOn)
                {
                    case true:
                        status = apiHelper(Properties.Settings.Default.ToggleOffUrlPart, Properties.Settings.Default.ToggleMethod, Properties.Settings.Default.ToggleData, toggleService);
                        break;
                    default:
                        status = apiHelper(Properties.Settings.Default.ToggleOnUrlPart, Properties.Settings.Default.ToggleMethod, Properties.Settings.Default.ToggleData, toggleService);
                        break;
                }
            }
            catch (Exception)
            {
                //change icon text to error
                notifyIcon.Text = "Error: Toggle failed to callback";
                status = 0;
            }

            // if worked, change sevice status and icon
            if (status == 1)
            {
                serviceOn = !serviceOn;
                notifyIcon.Icon = getIcon(serviceOn);
            }
        }
        // hander for system shutdown, try turning off
        public void SessionEndHandler(object sender, EventArgs e)
        {
            int status = apiHelper(Properties.Settings.Default.ToggleOffUrlPart, Properties.Settings.Default.ToggleMethod, Properties.Settings.Default.ToggleData, toggleService);
        }
    }
}
